home *** CD-ROM | disk | FTP | other *** search
/ BMUG PD-ROM B4 / PD-ROM B4.iso / Utilities / Text and Speech / Alpha 5.3 / Tcl / ElectricAlias / electricAlias.tcl
Encoding:
Text File  |  1993-02-02  |  23.8 KB  |  772 lines  |  [TEXT/ALFA]

  1. # FILE: electricAlias.tcl
  2. #
  3. # LAST UPDATE: 01/23/93 9:11:39 PM
  4. #
  5. # This file contains the following TCL procedures:
  6. #
  7. #   electricAlias-version   -- returns the current version of electricAlias
  8. #   electricAlias-help      -- opens 'electricAlias help' read-only
  9. #   electricAlias-on        -- turns on (enables) electricAlias-insert
  10. #   electricAlias-off       -- turns off (disables) electricAlias-insert
  11. #   electricAlias-mode      -- set/list current electricAlias mode
  12. #   electricAlias-def       -- creates an electricAlias definition
  13. #   electricAlias-var       -- creates an electricAlias variable
  14. #   electricAlias-exists    -- returns true/false 
  15. #   electricAlias-list      -- returns a list of electricAlias definitions
  16. #   electricAlias-names     -- returns a list of active electricAliases
  17. #   electricAlias-idefine   -- interactive define
  18. #   electricAlias-iundefine -- interactive undefine
  19. #   electricAlias-removeall -- removes all electricAlias definitions
  20. #   electricAlias-undefine  -- removes an electricAlias definition
  21. #   electricAlias-insert    -- on-the-fly template insertion (the real guts of this thing) 
  22. #   electricAlias           -- for compatibility with old version
  23. #   getAlias                -- returns a specific current alias definition
  24. #   nextStop                -- finds the next template stop
  25. #   prevStop                -- finds the previous template stop
  26. #   askalias                -- prompts the user for a value to set an alias variable
  27. #   changeMode              -- new version to enable electricAlias (renames old
  28. #                              version to 'original-changeMode')
  29. #
  30. # 'electricAlias-insert' (bound to TAB) provides automatic template/aliasing on the fly.
  31. #
  32. #    For documentation, see 'electricAlias help'. For examples, see 'aliases'. 
  33. #
  34. #    To use, simply place this file place in a folder named $HOME:Tcl:electricAlias:
  35. #    and add 'source $HOME:Tcl:electricAlias:electricAlias.tcl' to AlphaBits.tcl.
  36. #    Also create a folder named $HOME:TCL:electricAlias:Aliases and make sure to place
  37. #    at least a file named 'Aliases' in it with your default aliases.
  38. #    If you wish to use the language extensions feature, place respective
  39. #    files 'Aliases.Tcl', 'Aliases.C', etc.. there as well.
  40. #
  41. # IMPORTANT NOTE
  42. #   *********************************************************************
  43. #   * When changing to a mode for the first time in an Alpha session    *
  44. #   * (e.g. editing a C program), there may be a noticable delay as the *
  45. #   * appropriate aliases are loaded.  This is done rather than loading *
  46. #   * everything at startup to save memory and startup time.  This only *
  47. #   * occurs once per session per mode.                                 *
  48. #   *********************************************************************
  49. #
  50. #
  51. # SEE ALSO unknown.tcl, date.tcl, update.tcl, number.tcl
  52. #
  53. ################################################################################
  54.  
  55. # COPYRIGHT:
  56. #
  57. #    Copyright © 1992,1993 by David C. Black
  58. #    All rights reserved.
  59. #
  60. #    Redistribution and use in source and binary forms are permitted
  61. #    provided that the above copyright notice and this paragraph are
  62. #    duplicated in all such forms and that any documentation,
  63. #    advertising materials, and other materials related to such
  64. #    distribution and use acknowledge that the software was developed
  65. #    by David C. Black.
  66. #
  67. #    THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  68. #    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  69. #    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  70. #
  71. ################################################################################
  72.  
  73. # AUTHOR
  74. #
  75. #    David C. Black
  76. #    Internet: black@mpd.tandem.com (preferred)
  77. #    GEnie:    D.C.Black
  78. #    USnail:   6217 John Chisum Lane, Austin, TX 78749
  79. #
  80. ################################################################################
  81.  
  82. # HISTORY
  83. #                  
  84. # modified who rev reason
  85. # -------- --- --- ------ 
  86. # 01/23/93 DCB 1.7 Changed default locations
  87. #                  Split electricAlias into multiple specialized proc's
  88. # 01/06/93 DCB 1.6 Removed electricEnter, date, update, number to
  89. #                  separate .tcl files
  90. #                  Simplified installation
  91. #                  Added weekday, month, day, year to date proc
  92. #                  Fixed electricEnter & §«TCL_COMMAND» to work at global level
  93. #                  Changed bind to TAB
  94. #                  Added electricAlias help sub-command
  95. #                  'delete' now requires MODE
  96. #                  'add' renamed to 'interactive-add'
  97. #                  'remove' renamed to 'interactive-remove'
  98. #                  'list','names' & 'removeall' now allow restriction to a particular mode
  99. #                  'define' & 'variable' now return definition if not provided
  100. #                  Added askalias proc for use in definitions
  101. #                  Added getAlias proc
  102. #                  •-templates now require that they also be at end of line
  103. #                  Corrected \b\b && ^\b substitutions
  104. #                  Modified temporary marks to be window specific
  105. #                  Added 'update' proc
  106. # 11/23/92 DCB 1.5 Included definition of 'nextStop' proc
  107. #                  Changed 'stop's to 'st•p's to avoid collisions with permanent marks
  108. #                  aliasmode is now forced to lowercase
  109. #                  'electricAlias mode' without arg now 'return's the mode
  110. #                  Added 'electricAlias removeall' command
  111. #                  Fixed 'electricAlias list' bug with variables
  112. #                  Nil-mode alias variable now treated as global
  113. #                  Reversed ordering of HISTORY
  114. # 11/18/92 DCB 1.4 'electricAlias mode' now uses/require MODE argument
  115. #                  Modified 'date' proc
  116. # 11/17/92 DCB 1.3 Fixed nasty missing \] in §«TCL_COMMAND»
  117. # 11/16/92 DCB 1.2 Prevent • from appearing in variable mode definitions
  118. #                  §«TCL_COMMAND» now does each invocation separately
  119. #                  §«TCL_COMMAND» now uses [eval]
  120. #                  One minor typo
  121. #                  Non-• templates are now recognized at the beginning of a line
  122. #                  electricEnter now inserts in the correct window
  123. #                  Documented 'date' proc & added 'number' proc (useful in aliases)
  124. #                  Minor comment editing/formatting
  125. # 11/15/92 DCB 1.1 Added {version} command
  126. #                  Code to sub \n for \r in {define} and {variable}
  127. #                  Limit variable substitutions to 99 per template (avoid infinite)
  128. #                  Limit • mode templates to non-nil major modes
  129. #                  Added electric commands §«TCL_COMMAND»
  130. # 11/14/92 DCB 1.0 Original
  131. ################################################################################
  132.  
  133. # DESIGN NOTES
  134. # electricAlias uses a single array ALIAS to store all of its data. Aliases 
  135. # themselves are stored as ALIAS(mode,name). This means that commas are not 
  136. # allowed in mode names (not a severe restriction). State information is 
  137. # stored in ALIAS(name). 
  138. # To make it easier to undo an unintentional template, insertText is called
  139. # once with the normal insertion of a space.  If a template succeeds, then the
  140. # matched word is replaced.  To get back to the plain insertion, just UNDO
  141. # (CMD-Z) twice!  To undo all the way you need one more undo.
  142. #
  143. # Also, if text is selected then the template checking is always abandoned
  144. # in favor of a real space.
  145. # WARNING: If binding to another key is desired, be sure to change the
  146. # definition of $bindKey appropriately.
  147. #
  148. # Use of the bullet (•) to flag stops was arbitrary to some extent.  It had
  149. # to be something easy to use, but not a normal part of programming languages.
  150. # It also needed to be something that would not need special escaping in a
  151. # regular expression.  The same is true for alias variables.
  152. #
  153. ################################################################################
  154.  
  155. # IDEA/REQUEST/TODO
  156. # electricFunc -or- How to recognize procedural definitions on the fly so 
  157. # that later instantiations/calls can automatically insert the correct
  158. # template?  This should be extensible to several languages.
  159. #
  160. # For example in C, I can define 'int max(int a,int b) { return a>b ? a : b }'.
  161. # Later when I type 'x = max(', I would get 'x = max(a,b)' with 'a,b' 
  162. # automatically selected.
  163. # In Verilog, this is complicated by name parameters. For example a definition:
  164. # 'module myAnd (y,a,b); input a,b; output y; assign y = a & b; endmodule'
  165. # should be instantiated with 'myAnd THIS1(.a(a_wire),.b(b_wire));'.
  166. # The justification for the entire electricFunc concept is that frequently
  167. # modules may have literally tens of connections and leaving one out or
  168. # misnaming can be disasterous. The same happens occasionally in C or you
  169. # forget the names of the parameters (more likely).
  170. #
  171. ################################################################################
  172.  
  173. #message "Loading electric.tcl"
  174.  
  175. # Define global array for state/alias data
  176. if {[info exists ALIAS(active)] == 0} {
  177.     if {[info exists ALIAS] == 1} {
  178.         # Its scalar and we need an array
  179.         unset ALIAS
  180.     }
  181.     set ALIAS(active) 1
  182.     set ALIAS(mode)   "tcl"
  183.     set ALIAS(modes)  {tcl,}
  184. }
  185. #
  186. ################################################################################
  187.  
  188. proc electricAlias-version {} {
  189.     return "electricAlias version 1.7"
  190. }
  191. #endproc electricAlias-version
  192. ##############################################################################
  193.  
  194. proc electricAlias-help {} {
  195.     set helpDirs {$HOME:Help $HOME}
  196.     set helpFile "electricAlias Help"
  197.     foreach helpDir $helpDirs{
  198.         if {[file exists $helpDir:$helpFile} {
  199.             edit -r -m $helpDir:$helpFile
  200.             return
  201.         }
  202.     }
  203. }
  204. #endproc electricAlias-help
  205. ##############################################################################
  206.  
  207. proc electricAlias-on {} {
  208.     global ALIAS
  209.     set ALIAS(active) 1
  210. }
  211. #endproc electricAlias-on
  212. ##############################################################################
  213.  
  214. proc electricAlias-off {} {
  215.     global ALIAS
  216.     set ALIAS(active) 0
  217. }
  218. #endproc electricAlias-off
  219. ##############################################################################
  220.  
  221. proc electricAlias-mode {args} {
  222.     global ALIAS
  223.     set argc [llength $args]
  224.     set aliasmode $ALIAS(mode)
  225.     if {$argc > 1} {
  226.         error "Usage: electricAlias-mode ?NAME?"
  227.     }
  228.     if {$argc == 0} {
  229.         return $aliasmode
  230.     }
  231.     set aliasmode [string tolower [lindex $args 0]]
  232.     if {[regexp {[,]} $aliasmode]} {
  233.         error "Alias modes may not include commas"
  234.     }
  235.     set ALIAS(active) 1
  236.     regsub {^•} "$aliasmode" "" aliasmode
  237.     set ALIAS(mode) "$aliasmode"
  238.     if {[lsearch $ALIAS(modes) $aliasmode,] < 0} {
  239.         lappend ALIAS(modes) $aliasmode,
  240.     }
  241.     #message "Aliasmode $aliasmode"    
  242. }
  243. #endproc electricAlias-mode
  244. ##############################################################################
  245.  
  246. proc electricAlias-def {args} {
  247.     global ALIAS
  248.     set aliasmode [string tolower [lindex $args 0]]
  249.     set argc [llength $args]
  250.     if {$argc < 2 || $argc > 3} {
  251.         error "Usage: electricAlias-def MODE NAME ?DEFINITION?"
  252.     }
  253.     set aliasmode [string tolower [lindex $args 0]]
  254.     if {[regexp {[,]} $aliasmode]} {
  255.         error "Alias modes may not include commas"
  256.     }
  257.     set name      [lindex $args 1]
  258.     if {$argc == 2} {
  259.         return [getAlias $aliasmode $name]
  260.     }
  261.     set defn      [lindex $args 2]
  262.     regsub -all "\n" $defn "\r" defn
  263.     set ALIAS($aliasmode,$name) $defn
  264.     if {[lsearch $ALIAS(modes) $aliasmode,] < 0} {
  265.         lappend ALIAS(modes) $aliasmode,
  266.     }
  267. }
  268. #endproc electricAlias-def
  269. ##############################################################################
  270.  
  271. proc electricAlias-var {args} {
  272.     global ALIAS
  273.     set aliasmode [string tolower [lindex $args 0]]
  274.     set argc [llength $args]
  275.     if {$argc < 2 || $argc > 3} {
  276.         error "Usage: electricAlias-var MODE NAME ?DEFINITION?"
  277.     }
  278.     set aliasmode [string tolower [lindex $args 0]]
  279.     if {[regexp {[,]} $aliasmode]} {
  280.         error "Alias modes may not include commas"
  281.     }
  282.     set name      [lindex $args 1]
  283.     if {$argc == 2} {
  284.         return [getAlias $aliasmode $name]
  285.     }
  286.     set defn      [lindex $args 2]
  287.     regsub -all "\n" $defn "\r" defn
  288.     set ALIAS($aliasmode,§\{$name\}) $defn
  289.     if {[lsearch $ALIAS(modes) $aliasmode,] < 0} {
  290.         lappend ALIAS(modes) $aliasmode,
  291.     }
  292. }
  293. #endproc electricAlias-var
  294. ##############################################################################
  295.  
  296. proc electricAlias-exists {args} {
  297.     global ALIAS
  298.     set argc [llength $args]
  299.     if {$argc != 2} {
  300.         error "Usage: electricAlias-exists MODE NAME"
  301.     }
  302.     set aliasmode [string tolower [lindex $args 0]]
  303.     set name [lindex $args 1]
  304.     return [info exists ALIAS($aliasmode,$name)]
  305. }
  306. #endproc electricAlias-exists
  307. ##############################################################################
  308.  
  309. proc electricAlias-list {args} {
  310.     global ALIAS
  311.     set argc [llength $args]
  312.     set aliasmode $ALIAS(mode)
  313.     if {$argc > 1} {
  314.         error "Usage: electricAlias-list ?MODE?"
  315.     }
  316.     if {$argc == 1} {
  317.         set theMode [string tolower [lindex $args 0]]
  318.         if {[regexp {[,]} $theMode]} {
  319.             error "Alias modes may not include commas"
  320.         }
  321.     } else {
  322.         set theMode ""
  323.     }
  324.     set list {}
  325.     set count 1
  326.     foreach name [array names ALIAS] {
  327.         incr count
  328.         set index [split $name ","]
  329.         if {[llength $index] >= 2} {
  330.             set name [join [lrange $index 1 end] ","]
  331.             set aliasmode [lindex $index 0]
  332.             if {$theMode == "" || $aliasmode == $theMode || "$aliasmode" == "•$theMode"} {
  333.                 lappend list [getAlias $aliasmode $name]
  334.             }
  335.         }
  336.     }
  337.     #endforeach
  338.     return [join [lsort $list] "\r"]
  339. }
  340. #endproc electricAlias-list
  341. ##############################################################################
  342.  
  343. proc electricAlias-names {args} {
  344.     global ALIAS
  345.     set argc [llength $args]
  346.     set aliasmode $ALIAS(mode)
  347.     if {$argc > 1} {
  348.         error "Usage: electricAlias-names ?MODE?"
  349.     }
  350.     if {$argc == 1} {
  351.         set theMode [string tolower [lindex $args 0]]
  352.         if {[regexp {[,]} $theMode]} {
  353.             error "Alias modes may not include commas"
  354.         }
  355.     } else {
  356.         set theMode ""
  357.     }
  358.     set list {}
  359.     foreach name [array names ALIAS] {
  360.         set index [split $name ","]
  361.         if {[llength $index] < 2} {
  362.             continue
  363.         }
  364.             if {$theMode == "" || $aliasmode == $theMode || "$aliasmode" == "•$theMode"} {
  365.             lappend list "$name"
  366.         }
  367.     }
  368.     #endforeach
  369.     return [lsort $list]
  370. }
  371. #endproc electricAlias-names
  372. ##############################################################################
  373.  
  374. proc electricAlias-idefine {} {
  375.     global ALIAS
  376.     set aliasmode $ALIAS(mode)
  377.     set list [lsort $ALIAS(modes)]
  378.     catch {set name [eval [concat {prompt "Add mode,name:" "" Modes} $list]]}
  379.     if {[info exists name] == 0} { return }
  380.     if {$name == ""} { return }
  381.     if {[string first $name ","] < 0} {
  382.         set aliasmode [string range $name 0 [expr {$ind-1}]]
  383.         set name "$aliasmode,$name"
  384.     }
  385.     if {$name == ""} { return }
  386.     if {[info exists ALIAS($name)} {
  387.         if {[askyesno "Replace existing definition?"] != "Yes"} { return }
  388.     }
  389.     set defn [prompt "Definition of \"$name\":" ""]
  390.     if {$defn == ""} { return }
  391.     set ALIAS($name) $defn
  392.     message "Defined $name"
  393. }
  394. #endproc electricAlias-idefine
  395. ##############################################################################
  396.  
  397. proc electricAlias-iundefine {} {
  398.     global ALIAS
  399.     set list [electricAlias-names]
  400.     catch {set name [eval [concat {prompt {Remove mode,alias:} [lindex $list 0] Alias} $list]]}
  401.     if {[info exists name]} {
  402.         if {[string first $name ","] >= 0} {
  403.             unset ALIAS($name)
  404.             message "Removed $name"
  405.             unset name
  406.         }
  407.     }
  408. }
  409. #endproc electricAlias-iundefine
  410. ##############################################################################
  411.  
  412. proc electricAlias-removeall {args} {
  413.     global ALIAS
  414.     set argc [llength $args]
  415.     set aliasmode $ALIAS(mode)
  416.     if {$argc > 1} {
  417.         error "Usage: electricAlias-removeall ?MODE?"
  418.     }
  419.     if {$argc == 1} {
  420.         set theMode [string tolower [lindex $args 0]]
  421.         if {[regexp {[,]} $theMode]} {
  422.             error "Alias modes may not include commas"
  423.         }
  424.     } else {
  425.         set theMode ""
  426.     }
  427.     foreach name [array names ALIAS] {
  428.         if {[string first "," $name] >= 0} {
  429.             set aliasmode = [lindex [split $name ","] 0]
  430.             if {$theMode == "" || $aliasmode == $theMode || "$aliasmode" == "•$theMode"} {
  431.                 unset ALIAS($name)
  432.             }
  433.         }
  434.     }
  435.     #endforeach
  436. }
  437. #endproc electricAlias-removeall
  438. ##############################################################################
  439.  
  440. proc electricAlias-undefine {aliasmode name} {
  441.     global ALIAS
  442.     set aliasmode [string tolower $aliasmode]
  443.     if {[regexp {[,]} $aliasmode]} {
  444.         error "Alias modes may not include commas"
  445.     }
  446.     if {[info exists ALIAS($aliasmode,$name)] == 0} {
  447.         error "electricAlias does not exist!"
  448.     }
  449.     unset ALIAS($aliasmode,$name)
  450. }
  451. #endproc electricAlias-undefine
  452. ##############################################################################
  453.  
  454. proc electricAlias-insert {args} {
  455.     global ALIAS
  456.     set aliasmode $ALIAS(mode)
  457.     set bindKey "\t"
  458.     set argc [llength $args]
  459.  
  460.     if {$argc == 0} {
  461.         if {[getSelect]   != "" }  then {
  462.             replaceText [getPos] [selEnd] $bindKey
  463.             forwardChar
  464.             return
  465.         }
  466.         if {$ALIAS(active) == 0} {
  467.             insertText $bindKey
  468.             return
  469.         }
  470.         set match 0
  471.         set args [list normal]
  472.         set pos [getPos]
  473.         set bol [getText [lineStart $pos] $pos]
  474.         set eol [getText [expr {$pos}] [nextLineStart $pos]]
  475.         set modMode ""
  476.         # First token on the line?
  477.         if {! $match } {
  478.             if {[regexp {^([     ]*)([^     ]+)$} $bol all indent name]} {
  479.                 if {[regexp "^\[     \]*\[\r\n\]?\$" $eol all]} {
  480.                     set args [list insert "$indent" "$name"]
  481.                     set modMode "•"
  482.                     set match 1
  483.                 }
  484.             }
  485.         }
  486.  
  487.         # Word token?
  488.         if {! $match && [regexp {([     ]+)([^     ]+)$} "$bol" all indent name] == 1} {
  489.             set args [list insert "" "$name"]
  490.             set match 1
  491.         }
  492.  
  493.         insertText "$bindKey"
  494.     }
  495.  
  496.     set cmnd [lindex $args 0]
  497.     set args [lreplace $args 0 0]
  498.     set argc [llength $args]
  499.  
  500.     if {$cmnd == "normal"} {
  501.         return
  502.     }
  503.  
  504.     set indent [lindex $args 0]
  505.     set name [lindex $args 1]
  506.     set match 0
  507.  
  508.     # • mode template?
  509.     if {$match == 0 && $modMode == "•" && [info exists ALIAS($modMode$aliasmode,$name)] == 1} {
  510.         set defn "$ALIAS($modMode$aliasmode,$name)"
  511.         set match 1
  512.     }
  513.  
  514.     # embedded word template?
  515.     if {$match == 0 && [info exists ALIAS($aliasmode,$name)] == 1} {
  516.         set defn "$ALIAS($aliasmode,$name)"
  517.         set match 2
  518.     }
  519.  
  520.     # nil mode • definition matches everything iff non-nil aliasmode
  521.     if {$match == 0 && $modMode == "•"  && $aliasmode != "" && [info exists ALIAS(•,$name)] == 1} {
  522.         set defn "$ALIAS(•,$name)"
  523.         set match 3
  524.     }
  525.  
  526.     # nil mode matches everything
  527.     if {$match == 0 && [info exists ALIAS(,$name)] == 1} {
  528.         set defn "$ALIAS(,$name)"
  529.         set indent ""
  530.         set match 4
  531.     }
  532.  
  533.     # Next line for debug:
  534.     #message "$modMode $aliasmode $name -> $match"
  535.  
  536.     # return if no aliases found
  537.     if {$match == 0} { 
  538.         return
  539.     }
  540.  
  541.     # Perform substitutions
  542.     set limit 99
  543.     set doAnotherSubstitute 1
  544.     while {$doAnotherSubstitute} {
  545.         set doAnotherSubstitute 0
  546.         # substitute commands §«TCL_COMMAND»
  547.         while {[regexp {§«([^»]+)»} $defn all text] == 1} {
  548.             global _text
  549.             global _returnText
  550.             set _text $text
  551.             set _returnText ""
  552.             set errcode [uplevel #0 {catch $_text _returnText}]
  553.             if {$errcode != 0} {
  554.                 set _returnText "§ERROR $errcode($_text->$_returnText)"
  555.             }
  556.             regsub {§«([^»]+)»} $defn $_returnText defn
  557.             set doAnotherSubstitute 1
  558.             if {[incr limit -1] <= 0} {
  559.                 error "Too many electricAlias command substitutions"
  560.             }
  561.             unset _text
  562.             unset _returnText
  563.         }
  564.         #endwhile substitute cmds
  565.  
  566.         # substitute vars §{NAME}
  567.         while {[regexp {§\{[A-Za-z0-9_-]+\}} $defn var] == 1} {
  568.             if {[info exists ALIAS($aliasmode,$var)] == 1} {
  569.                 set repl $ALIAS($aliasmode,$var)
  570.             } else {
  571.                 # Does a global version of the variable exist?
  572.                 if {[info exists ALIAS(,$var)] == 1} {
  573.                     set repl $ALIAS(,$var)
  574.                 } else {
  575.                     set repl ""
  576.                 }
  577.             }
  578.             regsub -all $var $defn $repl defn
  579.             if {[info exists ALIAS($aliasmode,$var)] == 0 && [info exists ALIAS(,$var)] == 0} {
  580.                 alertnote "No such electricAlias variable $var"
  581.             }
  582.             set doAnotherSubstitute 1
  583.             if {[incr limit -1] <= 0} {
  584.                 alertnote "Too many electricAlias variable substitutions"
  585.             }
  586.         }
  587.         #endwhile substitute vars
  588.     }
  589.     #endwhile
  590.  
  591.     # substitute indents
  592.     regsub -all "\r" "$defn" "\r$indent" defn
  593.     set bs ""
  594.     if {[regexp "^\b+" $defn bs]} {
  595.         regsub "^\b+" "$defn" "" defn
  596.     }
  597.     while {[regsub ".\b" "$defn" "" defn]} {
  598.         ;
  599.     }
  600.     #endwhile
  601.  
  602.     # insert text and set stops
  603.     set repl "$defn"
  604.     regsub -all "•" "$repl" "" repl
  605.     set epos [getPos]
  606.     set bpos [expr {$epos - [string length "$name"] - 1}]
  607.     if {"$repl" == "$defn"} {
  608.         # Assert no stops to mark
  609.         if {$bs == "" && [regexp "\[^\n\r\t \]$" $repl] == 1} {
  610.             append repl " "
  611.         }
  612.         replaceText $bpos $epos "$repl"
  613.         goto [expr {$bpos + [string length "$repl"]}]
  614.         return
  615.     }
  616.     if {$bs != "" && $indent != ""} {
  617.         incr bpos [expr {-[string length $bs]}]
  618.     }
  619.     replaceText $bpos $epos "$repl"
  620.              global stopRing
  621.     set stopRing {}
  622.     set repl "$defn"
  623.     set win [lindex [winNames] 0]
  624.     set i 1
  625.     while {[regexp -indices "•" $repl I] == 1} {
  626.         regsub "•" "$repl" "" repl
  627.         createTMark "${win}•stop$i" [expr {$bpos + [lindex $I 0]}]
  628.         lappend stopRing "${win}•stop$i"
  629.         incr i
  630.     }
  631.     #endwhile
  632.  
  633.     gotoTMark "${win}•stop1"
  634.     bind 'j' <z> nextStop
  635.     bind 'j' <zs> prevStop
  636. }
  637. #endproc electricAlias-insert
  638.  
  639. bind '\t' electricAlias-insert
  640. ################################################################################
  641.  
  642. proc electricAlias {cmnd args} {
  643.     case {[llength $args]} {
  644.       {0} {electricAlias-$cmnd}
  645.       {1} {electricAlias-$cmnd [lindex $args 0]}
  646.       {2} {electricAlias-$cmnd [lindex $args 0] [lindex $args 1]}
  647.       {3} {electricAlias-$cmnd [lindex $args 0] [lindex $args 1] [lindex $args 2]}
  648.     }
  649.     #endcase
  650.     electricAlias-$cmnd $args
  651. }
  652. #endproc electricAlias
  653. ##############################################################################
  654.  
  655.  
  656. proc getAlias {aliasmode name} {
  657.     global ALIAS
  658.     if {![info exists ALIAS($aliasmode,$name)]} {
  659.         alertnote "getAlias: ?$aliasmode $name?"
  660.         return ""
  661.     }
  662.     set repl "$ALIAS($aliasmode,$name)"
  663.  
  664.     regsub -all "\r" "$repl" "\\r" repl
  665.     regsub -all "\n" "$repl" "\\n" repl
  666.     regsub -all "\t" "$repl" "\\t" repl
  667.     regsub -all "\b" "$repl" "\\b" repl
  668.     regsub -all {\$} "$repl" "\\\$" repl
  669.     regsub -all {\{} "$repl" "\\\{" repl
  670.     regsub -all {\}} "$repl" "\\\}" repl
  671.  
  672.     regsub -all {\$} "$name" "\\\$" name
  673.     regsub -all {\{} "$name" "\\\{" name
  674.     regsub -all {\}} "$name" "\\\}" name
  675.     regsub -all {\[} "$name" "\\\[" name
  676.     regsub -all {\]} "$name" "\\\]" name
  677.  
  678.     set cmnd "var"
  679.     if {[regexp {^§\\\{.*\}$} $name] == 0} {
  680.         set cmnd "def"
  681.         set name "\"$name\""
  682.     }
  683.     set fmt "electricAlias-%s %-8s %-10s \{%s\}"
  684.     return [format $fmt $cmnd "\"$aliasmode\"" $name $repl]
  685. }
  686. #endproc getAlias
  687. ################################################################################
  688.  
  689. proc nextStop {} {
  690.     global stopRing
  691.     set first [lindex $stopRing 0]
  692.     set stopRing [lreplace $stopRing 0 0]
  693.     lappend stopRing $first
  694.     set next [lindex $stopRing 0]
  695.     gotoTMark $next
  696.  
  697. }
  698. #endproc nextStop
  699. ################################################################################
  700.  
  701. proc prevStop {} {
  702.     global stopRing
  703.     set end [expr {[llength $stopRing] - 1}]
  704.     set last [lindex $stopRing $end]
  705.     set stopRing [lreplace $stopRing $end $end]
  706.     set stopRing [linsert $stopRing 0 $last]
  707.     gotoTMark $last
  708. }
  709. #endproc prevStop
  710. ################################################################################
  711.  
  712.  
  713. proc askalias {prompt name args} {
  714.     global mode
  715.     set argc [llength $args]
  716.     case $argc {
  717.     0 {
  718.         electricAlias var $mode $name [prompt $prompt ""]
  719.     }
  720.     1 {
  721.         set default $args
  722.         electricAlias var $mode $name [prompt $prompt $default]
  723.     }
  724.     {default} {
  725.         set default [lindex $args 0]
  726.         set title [lindex $args 1]
  727.         set list [lrange $args 2 end]
  728.         electricAlias var $mode $name [prompt $prompt $default $title $list]
  729.     }
  730.     }
  731.     return ""
  732. }
  733. #endproc askalias
  734. ################################################################################
  735.  
  736. if {![file isdirectory "$HOME:TCL:electricAlias:Aliases"]} {
  737.     mkdir $HOME:TCL:electricAlias:Aliases
  738. }
  739.  
  740. if {[file readable "$HOME:TCL:electricAlias:Aliases:Aliases"]} {
  741.     source $HOME:TCL:electricAlias:Aliases:aliases
  742. } else {
  743.     alertnote "No default file $HOME:TCL:electricAlias:Aliases:aliases"
  744. }
  745.  
  746. if {[info procs original-changeMode] != "original-changeMode"} {
  747.  
  748.     rename changeMode original-changeMode
  749.  
  750. proc changeMode {newMode} {
  751.     original-changeMode $newMode
  752.     global mode
  753.     global HOME
  754.     if {![electricAlias-exists "•$mode" "•$mode"] &&
  755.          [file readable "$HOME:TCL:electricAlias:Aliases:aliases.$mode"]} {
  756.         source "$HOME:TCL:electricAlias:Aliases:aliases.$mode"
  757.     }
  758.     electricAlias-mode "$mode"
  759. }
  760. #endproc changeMode
  761.  
  762. }
  763. #endif
  764. ################################################################################
  765.  
  766.